package model

import (
	"common/helper"
	"database/sql"
	"errors"
	"fmt"
	"math/rand"
	"strconv"
	"time"

	g "github.com/doug-martin/goqu/v9"
	"github.com/valyala/fasthttp"
)

// Admin 用户数据库结构体
type Admin struct {
	ID                 string `cbor:"id" db:"id" json:"id"`                                        // 主键ID
	GroupID            string `cbor:"group_id" db:"group_id" json:"group_id"`                      // 用户组ID
	LastLoginIP        string `cbor:"last_login_ip" db:"last_login_ip"`                            // 最后登录IP
	LastLoginTime      uint32 `cbor:"last_login_time" db:"last_login_time" json:"last_login_time"` // 最后登录时间
	Pwd                string `cbor:"password" db:"password" json:"password"`                      // 密码
	State              int    `cbor:"state" db:"state" json:"state"`                               // 状态
	Seamo              string `cbor:"seamo" db:"seamo" json:"seamo"`
	Name               string `cbor:"name" db:"name" json:"name"`                                              // 用户名
	CreateAt           uint32 `cbor:"create_at" db:"create_at" json:"create_at"`                               // 创建时间
	CreatedUid         string `cbor:"created_uid" db:"created_uid" json:"created_uid"`                         //创建人uid
	CreatedName        string `cbor:"created_name" db:"created_name" json:"created_name"`                      //创建人名
	UpdatedAt          uint32 `cbor:"updated_at" db:"updated_at" json:"updated_at"`                            // 修改时间
	UpdatedUid         string `cbor:"updated_uid" db:"updated_uid" json:"updated_uid"`                         //修改人uid
	UpdatedName        string `cbor:"updated_name" db:"updated_name" json:"updated_name"`                      //修改人名
	ImportantInfo      int    `cbor:"important_info" db:"important_info" json:"important_info"`                //重要信息
	SysConfigInfo      int    `cbor:"sysconfig_info" db:"sysconfig_info" json:"sysconfig_info"`                //游戏配置信息
	PlatformController int    `cbor:"platform_controller" db:"platform_controller" json:"platform_controller"` //平台控制
}

type AdminData struct {
	D []Admin `json:"d"`
	T int64   `json:"total"`
	S uint    `json:"s"`
}

// AdminLoginResp 用户登录返回数据结构体
type AdminLoginResp struct {
	Token     string `json:"token" cbor:"token"`           // 用户token
	Allows    string `json:"allows" cbor:"allows"`         // 用户权限列表
	AdminName string `json:"user_name" cbor:"admin_name"`  // 用户名
	Domain    string `json:"domain" cbor:"domain"`         // 用户名
	GroupId   string `json:"group_id" cbor:"group_id"`     //
	GroupName string `json:"group_name" cbor:"group_name"` //
	Date      int64  `json:"date" cbor:"date"`             //
	Seamo     string `json:"seamo" cbor:"seamo"`           //
	CodeUrl   string `json:"code_url" cbor:"code_url"`     //
}

func AdminInsert(data Admin) error {

	//v := MurmurHash(data.Pwd, data.CreateAt)
	v := data.Pwd
	enpwd, err := Encrypt(fmt.Sprintf("%s", v))
	if err != nil {
		return err
	}
	data.Pwd = enpwd
	rand.New(rand.NewSource(time.Now().UnixNano()))
	data.ID = strconv.Itoa(rand.Intn(100000))
	data.LastLoginIP = ""
	data.LastLoginTime = 0
	data.Seamo = ""
	query, _, _ := dialect.Insert("tbl_admins").Rows(data).ToSQL()

	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		body := fmt.Errorf("%s,[%s]", err.Error(), query)
		return pushLog(body, "数据库错误")
	}

	//log := fmt.Sprintf("系统管理/系统账号/新增 后台账号[%s],新增账号[%s],权限组id[%s],状态[%s] 新增",
	//	data.CreatedName, data.Name, data.GroupID, data.State)

	return nil
}

func AdminUpdateState(adminID, adminName, id, state string) error {

	ex := g.Ex{
		"id": id,
	}
	data := Admin{}
	query, _, _ := dialect.From("tbl_admins").Select(colsAdmin...).Where(ex).ToSQL()

	err := meta.MerchantDB.Get(&data, query)
	if err != nil && err != sql.ErrNoRows {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if err == sql.ErrNoRows {
		return errors.New(helper.RecordNotExistErr)
	}

	if state == fmt.Sprintf("%d", data.State) {
		return errors.New(helper.NoDataUpdate)
	}

	record := g.Record{
		"state":        state,
		"updated_at":   time.Now().Unix(),
		"updated_uid":  adminID,
		"updated_name": adminName,
	}
	query, _, _ = dialect.Update("tbl_admins").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	//if state == "0" {
	//	log := fmt.Sprintf("系统管理/系统账号/更新状态 后台账号[%s],被操作账号[%s] 关闭", adminName, data.Name)

	//} else {
	//	log := fmt.Sprintf("系统管理/系统账号/更新状态 后台账号[%s],被操作账号[%s] 开启", adminName, data.Name)

	//}

	return nil
}

func AdminUpdate(adminID, adminName, id, pwd, gid string, record g.Record) error {

	var gname string
	ex := g.Ex{
		"gid": gid,
	}
	query, _, _ := dialect.From("tbl_admin_group").Select("gname").Where(ex).ToSQL()

	err := meta.MerchantDB.Get(&gname, query)
	if err != nil && err != sql.ErrNoRows {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if err == sql.ErrNoRows {
		return errors.New(helper.GroupIDErr)
	}

	ex = g.Ex{
		"id": id,
	}
	data := Admin{}
	query, _, _ = dialect.From("tbl_admins").Select(colsAdmin...).Where(ex).ToSQL()

	err = meta.MerchantDB.Get(&data, query)
	if err != nil && err != sql.ErrNoRows {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if err == sql.ErrNoRows {
		return errors.New(helper.RecordNotExistErr)
	}

	record["updated_uid"] = adminID
	record["updated_name"] = adminName

	if pwd != "" {

		v := fmt.Sprintf("%s", pwd)
		enpwd, err := Encrypt(fmt.Sprintf("%s", v))
		if err != nil {
			return err
		}
		record["password"] = enpwd
	}

	query, _, _ = dialect.Update("tbl_admins").Set(record).Where(g.Ex{"id": id}).ToSQL()

	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	//log := fmt.Sprintf("系统管理/系统账号/更新 后台账号[%s],被更新账号[%s],sql[%s] 更新", adminName, data.Name, query)

	return nil
}

func AdminList(Admin Admin, page, pageSize uint, ex g.Ex) (AdminData, error) {

	data := AdminData{}
	gids, gidMap, err := groupSubList(Admin.GroupID)
	if err != nil {
		return data, err
	}

	if len(gids) == 0 {
		return data, nil
	}

	if gid, ok := ex["group_id"].(string); ok {
		if _, ok = gidMap[gid]; !ok {
			return data, errors.New("权限不足")
		}
	} else {
		ex["group_id"] = gids
	}

	if Admin.PlatformController != 1 {
		ex["platform_controller"] = 0
	}
	t := dialect.From("tbl_admins")
	if page >= 1 {
		query, _, _ := t.Select(g.COUNT(1)).Where(ex).ToSQL()
		err := meta.MerchantDB.Get(&data.T, query)
		if err != nil {
			body := fmt.Errorf("%s,[%s]", err.Error(), query)
			return data, pushLog(body, "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}

	offset := (page - 1) * pageSize
	query, _, _ := t.Select(colsAdmin...).Where(ex).Offset(offset).Limit(pageSize).Order(g.C("create_at").Desc()).ToSQL()

	err = meta.MerchantDB.Select(&data.D, query)
	if err != nil {
		body := fmt.Errorf("%s,[%s]", err.Error(), query)
		return data, pushLog(body, "数据库错误")
	}

	data.S = pageSize
	return data, nil

}
func GetAdminInfoByUsername(username string) (Admin, error) {
	data := Admin{}
	t := dialect.From("tbl_admins")
	query, _, _ := t.Select(colsAdmin...).Where(g.Ex{"name": username}).Limit(1).ToSQL()

	err := meta.MerchantDB.Get(&data, query)
	// 账号不存在提示
	if err == sql.ErrNoRows {
		return data, errors.New(helper.UserNotExist)
	}
	return data, nil
}

func GetAdminInfoById(Id string) (Admin, error) {
	data := Admin{}
	t := dialect.From("tbl_admins")
	query, _, _ := t.Select(colsAdmin...).Where(g.Ex{"id": Id}).Limit(1).ToSQL()
	err := meta.MerchantDB.Get(&data, query)
	// 账号不存在提示
	if err == sql.ErrNoRows {
		return data, errors.New(helper.UserNotExist)
	}
	return data, nil
}

func UpdateLoginInfo(id string, ip string) error {
	record := g.Record{
		"last_login_ip":   ip,
		"last_login_time": time.Now().Unix(),
	}
	query, _, _ := dialect.Update("tbl_admins").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		body := fmt.Errorf("%s,[%s]", err.Error(), query)
		return pushLog(body, "数据库错误")
	}
	return nil
}

func UpdateAdminPassword(id string, password string) error {
	record := g.Record{
		"password": password,
	}
	query, _, _ := dialect.Update("tbl_admins").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		body := fmt.Errorf("%s,[%s]", err.Error(), query)
		return pushLog(body, "数据库错误")
	}
	return nil
}

func UpdateGoogleSecret(id string, seamo string) error {
	record := g.Record{
		"seamo": seamo,
	}
	query, _, _ := dialect.Update("tbl_admins").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		body := fmt.Errorf("%s,[%s]", err.Error(), query)
		return pushLog(body, "数据库错误")
	}
	return nil
}

func UpdateState(id string, state int) error {
	record := g.Record{
		"state": state,
	}
	query, _, _ := dialect.Update("tbl_admins").Set(record).Where(g.Ex{"id": id}).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		body := fmt.Errorf("%s,[%s]", err.Error(), query)
		return pushLog(body, "数据库错误")
	}
	return nil
}

// 检测管理员账号是否已存在
func AdminExist(ex g.Ex) bool {

	var id string

	t := dialect.From("tbl_admins")
	query, _, _ := t.Select("id").Where(ex).Limit(1).ToSQL()
	err := meta.MerchantDB.Get(&id, query)
	return err != sql.ErrNoRows
}

// 后台管理员退出登录
func AdminLogout(ctx *fasthttp.RequestCtx) {
	key := string(ctx.Request.Header.Peek("t"))
	meta.MerchantRedis.Del(ctx, key)
}

func getAuth(ctx *fasthttp.RequestCtx) {

}
func GetLogList(param BackgroundLogParam, ctx *fasthttp.RequestCtx) (BackgroundLogRetData, error) {
	data := BackgroundLogRetData{}
	where := "1=1"
	oderBy := "id"
	oderType := "desc"
	if param.Name != "" {
		where += " and name like '%" + param.Name + "%'"
	}
	if param.Param != "" {
		where += " and param like '%" + param.Param + "%'"
	}
	if param.Type > 0 {
		where += " and type=" + strconv.Itoa(param.Type)
	}
	if param.StartTime != "" {
		where += " and date>='" + param.StartTime + "'"
	}
	if param.EndTime != "" {
		where += " and date<='" + param.EndTime + "'"
	}
	if param.OptId != "" {
		where += " and opt_id=" + param.OptId
	}
	if param.Ip != "" {
		where += " and ip='" + param.Ip + "'"
	}
	if param.OderBY != "" {
		oderBy = param.OderBY
	}
	if param.OderType != "" {
		oderType = param.OderType
	}

	order := oderBy + " " + oderType

	offset := (param.Page - 1) * param.PageSize
	if param.Page >= 1 {
		count := "select count(1) from tbl_background_log where " + where

		err := meta.MerchantDB.Get(&data.T, count)
		if err != nil {

			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), count), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}
	field := "*"
	query := "select " + field + " from tbl_background_log where " + where + " order by " + order + " limit " + strconv.Itoa(param.PageSize) + " offset " + strconv.Itoa(offset)

	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil && err != sql.ErrNoRows {

		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	adminList, _ := GetAdminMap()
	businessList, _ := GetBusinessMap()
	operatorList, _ := GetOperatorMap()

	for key, _ := range data.D {
		OptId := strconv.Itoa((data.D)[key].OptId)
		len := len(OptId)
		if len == 5 {
			(data.D)[key].OptName = "总后台:" + adminList[OptId]
		}
		if len == 6 {
			(data.D)[key].OptName = "渠道:" + operatorList[OptId]
		}
		if len == 7 {
			(data.D)[key].OptName = "业务员:" + businessList[OptId]
		}
	}
	return data, nil
}
func GetAdmin(id int) ([]Admin, error) {

	data := []Admin{}
	where := " "
	if id > 0 {
		where = " where id<>" + strconv.Itoa(id)
	}
	query := "select id,name from tbl_admins " + where
	err := meta.MerchantDB.Select(&data, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	return data, nil
}

func GetAdminMap() (map[string]string, error) {
	data := map[string]string{}
	list, _ := GetAdmin(0)
	for _, val := range list {
		data[val.ID] = val.Name
	}
	return data, nil
}

func LoginLimit(admin Admin) {
	client := meta.MerchantRedis
	client.Incr(ctx, "总后台登陆："+admin.Name)
	errnum := client.Get(ctx, "总后台登陆："+admin.Name).Val()
	errnumint, _ := strconv.Atoi(errnum)
	if errnumint >= 5 {
		UpdateState(admin.ID, 0)
		client.Del(ctx, "总后台登陆："+admin.Name)
	}
}

func LoginUnLimit(admin Admin) {
	client := meta.MerchantRedis
	client.Del(ctx, "总后台登陆："+admin.Name)
}

func LoginmMerchantLimit(merchant TblOperatorInfo) {
	client := meta.MerchantRedis
	client.Incr(ctx, "渠道后台登陆："+merchant.OperatorName)
	errnum := client.Get(ctx, "渠道后台登陆："+merchant.OperatorName).Val()
	errnumint, _ := strconv.Atoi(errnum)
	if errnumint >= 10 {
		UpdateState(merchant.Id, 0)
		client.Del(ctx, "渠道后台登陆："+merchant.OperatorName)
	}
}

func LoginMerchantUnLimit(merchant TblOperatorInfo) {
	client := meta.MerchantRedis
	client.Del(ctx, "渠道后台登陆："+merchant.OperatorName)
}

func LoginBusinessLimit(business TblBusinessInfo) {
	client := meta.MerchantRedis
	client.Incr(ctx, "业务员后台登陆："+business.LoginAccount)
	errnum := client.Get(ctx, "业务员后台登陆："+business.LoginAccount).Val()
	errnumint, _ := strconv.Atoi(errnum)
	if errnumint >= 10 {
		UpdateBusinessState(business.Id, 0)
		client.Del(ctx, "业务员后台登陆："+business.LoginAccount)
	}
}

func LoginBusinessUnLimit(business TblBusinessInfo) {
	client := meta.MerchantRedis
	client.Del(ctx, "业务员后台登陆："+business.LoginAccount)
}
